home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / stut_src / dbsystem.c < prev    next >
Text File  |  1996-05-27  |  18KB  |  791 lines

  1. /*
  2.  * dbsystem.c
  3.  *
  4.  * Purpose:
  5.  * --------
  6.  * Routines de gestion du
  7.  * SystŠme de Gestion de Bases de Donn‚es (Relationnelles)
  8.  * Orient‚ R‚seau
  9.  * SGBDRR
  10.  *
  11.  * Notes:
  12.  * ------
  13.  * Designed by Fran‡ois Planque & Xavier Cany
  14.  *
  15.  * History:
  16.  * --------
  17.  * 1993: fplanque: Created
  18.  * 1994: fplanque: many revisions
  19.  */
  20.  
  21.    #include "!OPTIONS.H"                /* Options de compilation */         
  22.     #define    THIS_FILE    "DBSYSTEM.C v1.00 - 03.95"
  23.  
  24. /*
  25.  * System headers:
  26.  */
  27.     #include <stdio.h>
  28.     #include <stdlib.h>        /* rand */
  29.     #include <time.h>
  30.     #include <string.h>
  31.        
  32.  
  33. /*
  34.  * Custom headers:
  35.  */
  36.     #include    "SPEC_PU.H"
  37.     #include "S_MALLOC.H"
  38.     #include    "DEBUG_PU.H"    
  39.     #include "DBSYS_PU.H"
  40.     #include "MAIN_PU.H"
  41.  
  42. /*
  43.  * ------------------------ VARIABLES -------------------------
  44.  */
  45.     
  46. /*
  47.  * Public variables: 
  48.  */
  49.     RECORD_NUMBER    G_RecNb_Null = { 0, 0 };
  50.  
  51. /*
  52.  * Private variables: 
  53.  */
  54.     static    char    M_magic;                /* Magic number */
  55.      
  56.  
  57. /*
  58.  * ------------------------ FUNCTIONS -------------------------
  59.  */
  60.  
  61. /*
  62.  * init_dbsystem(-)
  63.  *
  64.  * Purpose:
  65.  * --------
  66.  * Init du S.G.B.D.
  67.  *
  68.  * Suggest:
  69.  * --------
  70.  * The MAGIC # should not be random. The Sysop should be allowed
  71.  * to change it.
  72.  *
  73.  * History:
  74.  * --------
  75.  * 1993: fplanque: Created
  76.  */
  77. void    init_dbsystem( void )
  78. {
  79.     /* 
  80.      * Nombre magique sp‚ciqiue au serveur: 
  81.      */
  82.         M_magic = (char) rand();            /* PROVISOIRE */
  83.  
  84.  
  85. }
  86.  
  87.  
  88. /*
  89.  * CompRec_Create(-)
  90.  *
  91.  * Cr‚ation d'un Compact Record
  92.  *
  93.  * 02.03.95: Created
  94.  */
  95. COMPACT_RECORD * CompRec_Create(                /* Out: ptr sur record cr‚‚ */
  96.                             size_t    size_data ) /* In: taille des donn‚es … stocker */
  97. {
  98.     /*
  99.      * On doit stocker un certain nombre de donn‚es suppl‚mentaires
  100.      * en plus des donn‚es:
  101.      */    
  102.     size_data += sizeof( void * );                    /* Ptr sur prev */
  103.     size_data += sizeof( void * );                    /* next */
  104.     size_data += sizeof( struct s_reclocks );        /* Readlocks sur le record */
  105.  
  106.     return    (COMPACT_RECORD *) MALLOC( size_data );
  107. }
  108.  
  109.  
  110. /*
  111.  * Create_HeaderFld(-)
  112.  *
  113.  * Purpose:
  114.  * --------
  115.  * Cr‚ation d'un HEADER d'enregistrement
  116.  *
  117.  * History:
  118.  * --------
  119.  * 1993: fplanque: Created
  120.  * 29.11.94: fplanque: chang‚ de fill_header() en Create_HeaderFld()
  121.  * 16.12.94: fplanque: gestion du flag private
  122.  */
  123. RECORD_FIELD    *    Create_HeaderFld(            /* Out: Champ cr‚‚ */
  124.         const RECORD_NUMBER    *    pRecNb_Ref,    /* In:  Id du message auquel on fait r‚f‚rence */
  125.         BOOL                            b_Private )    /* In:  !=0 si le message est priv‚ */
  126. {
  127.     HEAD_STRING        *    pHeadString;
  128.  
  129.     /*
  130.      * Cr‚e champ:
  131.      */
  132.     RECORD_FIELD    *    pRecField = MALLOC( sizeof( RECORD_FIELD ) );
  133.  
  134.     /* ID du champ: */
  135.     pRecField -> field_id = 'HEAD';
  136.  
  137.     /* Longueur du champ: */
  138.     pRecField -> length = sizeof( HEAD_STRING );
  139.  
  140.     /*
  141.      * Cr‚e les infos du HEADER:
  142.      */
  143.     pHeadString = MALLOC( sizeof( HEAD_STRING ) );
  144.     pRecField -> info.head = pHeadString;
  145.     
  146.     /*
  147.      * ----------------------------------------
  148.      * Longueur du message: 
  149.      * ----------------------------------------
  150.      * Inconnue pour l'instant, il faudra ABSOLUMENT la mettre … jour … la fin
  151.      */
  152.     pHeadString -> rec_length = NIL;        
  153.  
  154.     /*
  155.      * ----------------------------------------
  156.      * Num‚ro d'identification du message: 
  157.      * ----------------------------------------
  158.      * Date d'‚criture: 
  159.      */
  160.     time( &(pHeadString -> rec_idnb .date) );        /* Date d'‚criture format UNIX */
  161.                                     
  162.     /*
  163.      * Num‚ro de diff‚renciation (Exemple de gestion):
  164.      * Nombre "magique" que vous choisissez 
  165.      */
  166.     pHeadString -> rec_idnb .diff .fulc .magic = M_magic;    /* Octet "Magique" */
  167.  
  168.     /* Repeat Number */
  169.     pHeadString -> rec_idnb .diff .fulc .repeat = 71;    
  170.     /*
  171.      * Ce message est le 71eme ecrit par le connect‚ depuis l'ouverture
  172.      * se sa BAL; … 255, on repasse … 0... 
  173.      */
  174.  
  175.     /* Nombre al‚atoire */
  176.     pHeadString -> rec_idnb .diff .fulc .random = rand();    /* Num‚ro Random */
  177.  
  178.     /*
  179.      * ----------------------------------------
  180.      * Num‚ro d'identification du message auquel celui-ci fait r‚f‚rence: 
  181.      * ----------------------------------------
  182.      */
  183.     pHeadString -> ref_idnb = * pRecNb_Ref;
  184.  
  185.  
  186.     /*
  187.      * ----------------------------------------
  188.      * Flags de qualification du message:
  189.      * ----------------------------------------
  190.      */
  191.     pHeadString -> RecFlags.b_Private = b_Private; 
  192.     pHeadString -> RecFlags.n_Junk = 0;
  193.  
  194.     return        pRecField;
  195. }
  196.  
  197.  
  198.  
  199. /*
  200.  * Create_SimpleRecFld(-)
  201.  *
  202.  * Purpose:
  203.  * --------
  204.  * Cr‚ation d'un Field simple ds un record
  205.  * (un field dont on n'a qu'… coller le contenu(une PSZ) d‚j… tout prˆt)
  206.  *
  207.  * 27.11.94: fplanque: Created
  208.  */
  209. RECORD_FIELD    *    Create_SimpleRecFld(                    /* Out: champ cr‚‚ */
  210.                             unsigned    long    dw_FieldId,        /* In: Identificateur du champ */
  211.                             const char     *    cpsz_Content )    /* In: texte … recopier DANS le champ */
  212. {
  213.     size_t    field_length;
  214.     char    *    field_string;
  215.  
  216.     /*
  217.      * Cr‚e champ:
  218.      */
  219.     RECORD_FIELD    *    pRecField = MALLOC( sizeof( RECORD_FIELD ) );
  220.  
  221.     /*
  222.      * Pas de champ suivant pour l'instant:
  223.      */
  224.     pRecField -> next = NULL;
  225.  
  226.     /*
  227.      * ID du champ 
  228.      */
  229.     pRecField -> field_id = dw_FieldId;
  230.  
  231.     /*
  232.      * Longueur du champ:
  233.      */
  234.     field_length = ( strlen( cpsz_Content ) +2 ) & PARITY;  /* Longueur paire */
  235.     pRecField -> length = field_length;
  236.  
  237.     /*
  238.      * Cr‚e une chaine:
  239.      */
  240.     field_string = (char *) MALLOC( field_length );            /* R‚serve m‚moire */
  241.     memcpy( field_string, cpsz_Content, field_length );    /* Y recopie les donn‚es */
  242.     field_string[ field_length - 1 ] = '\0';                    /* Octet nul comblant le trou si long ‚tait impaire ou ‚crasant l'octet de fin de chaine si long ‚tait d‚j… paire */
  243.     pRecField -> info.string = field_string;                /* Sauve adresse */
  244.  
  245.     return        pRecField;
  246. }
  247.  
  248.  
  249. /*
  250.  * Create_FooterFld(-)
  251.  *
  252.  * Purpose:
  253.  * --------
  254.  * Cr‚ation d'un FOOTER d'enregistrement
  255.  *
  256.  * History:
  257.  * --------
  258.  * 29.11.94: fplanque: Created
  259.  */
  260. RECORD_FIELD    *    Create_FooterFld( void )    /* Out: Champ cr‚‚ */
  261. {
  262.     FOOT_STRING        *    pFootString;
  263.  
  264.     /*
  265.      * Cr‚e champ:
  266.      */
  267.     RECORD_FIELD    *    pRecField = MALLOC( sizeof( RECORD_FIELD ) );
  268.  
  269.     /* ID du champ: */
  270.     pRecField -> field_id = 'FOOT';
  271.  
  272.     /* Longueur du champ: */
  273.     pRecField -> length = sizeof( FOOT_STRING );
  274.  
  275.     /*
  276.      * Cr‚e les infos du FOOTER:
  277.      */
  278.     pFootString = MALLOC( sizeof( FOOT_STRING ) );
  279.     pRecField -> info.foot = pFootString;
  280.     
  281.     /*
  282.      * Checksum du message: 
  283.      * Inconnu pour l'instant, il faudra ABSOLUMENT le mettre … jour … la fin
  284.      */
  285.     pFootString -> checksum = 0;        
  286.  
  287.     return        pRecField;
  288. }
  289.  
  290.  
  291.  
  292. /*
  293.  * record_length(-)
  294.  *
  295.  * Purpose:
  296.  * --------
  297.  * D‚termine la longueur totale d'un message
  298.  *
  299.  * History:
  300.  * --------
  301.  * 1993: fplanque: Created
  302.  */
  303. size_t    record_length( 
  304.                 RECORD_FIELD *field_ptr ) /* In: ptr sur champ header */
  305. {    
  306.     size_t    record_length = 0;
  307.             
  308.     /*
  309.      * Longueur des segments 
  310.      */
  311.     while    ( field_ptr != NULL )    /* Tant qu'on est pas … la fin de l'enregsitrement */
  312.     {
  313.         record_length +=      sizeof ( field_ptr -> field_id )    /* Taille d'une ID de champ */
  314.                                  + sizeof ( field_ptr -> length )        /* Taille de la taille (!) */
  315.                                  + field_ptr -> length;                    /* Taille du texte du champ */
  316.         field_ptr = field_ptr -> next;    /* Pointe sur prochain segment */
  317.     }
  318.  
  319.     /*
  320.      * Retourne longueur totale: 
  321.      */
  322.     return    record_length;
  323. }
  324.  
  325.  
  326. /*
  327.  * Create_CompactRecord(-)
  328.  *
  329.  * Purpose:
  330.  * --------
  331.  * Cr‚e un enregistrement sous forme compact‚e
  332.  *
  333.  * History:
  334.  * --------
  335.  *     1993: fplanque: Created
  336.  * 05.12.94: fplanque: changed name from fill_compact_record() and included creation code
  337.  * 11.07.95: fplanque: correction dela taille du malloc (on d‚bordait)
  338.  */
  339. COMPACT_RECORD *    Create_CompactRecord( 
  340.                             RECORD_FIELD     *    field_ptr )
  341. {
  342.     COMPACT_RECORD *    pCompactRec;
  343.     char                *    tmp_msg_start;                    /* Adresse de d‚part du message compact‚ */
  344.     char                *    tmp_msg_csr;                     /* Pointeur dans le message complet */
  345.     char                *    last_string_adr = NULL;        /* Adr du dernier string compact‚ */
  346.     char                *    tmp_msg_check;                    /* Le mˆme pour checksum */
  347.     unsigned int        checksum = 0;                    /* Checksum... */
  348.     
  349.  
  350.     /*
  351.      * +------------------------------+ 
  352.      * |  Longueur totale du message  |
  353.      * +------------------------------+
  354.      */
  355.     size_t    rec_length = record_length( field_ptr );        /* Calcul */
  356.  
  357.     /*
  358.      * Taille occupp‚e en m‚moire avec 2 pointeurs (sur prev et next)
  359.      * ainsi que la taille allou‚e aux readlocks: 
  360.      */
  361.     size_t    rec_memsize = rec_length 
  362.                                         + 2 * sizeof( COMPACT_RECORD * )
  363.                                         + sizeof( struct    s_reclocks );
  364.  
  365.     /*
  366.      * Indique la longueur totale dans les infos du header: 
  367.      */
  368.     field_ptr -> info.head -> rec_length = rec_length;
  369.  
  370.  
  371.     /*
  372.      * ----------------------------
  373.      * Alloue une zone en m‚moire :
  374.      * ----------------------------
  375.      */
  376.     pCompactRec = (COMPACT_RECORD *) MALLOC ( rec_memsize );
  377.     tmp_msg_start = pCompactRec -> data.compact_rec;    /* Adresse de d‚part du message compact‚ */
  378.     tmp_msg_csr = tmp_msg_start;     /* Pointeur dans le message complet */
  379.  
  380.     /*
  381.      * ----------------------------
  382.      * remplissage du msg compact‚:
  383.      * ----------------------------
  384.      * Les ptr sur PREV et NEXT seront fix‚s ult‚rieurement! 
  385.      */
  386.     pCompactRec -> prev = NULL;
  387.     pCompactRec -> next = NULL;
  388.  
  389.     /*
  390.      * Recopie le contenu des Champs: 
  391.      */
  392.     while    ( field_ptr != NULL )    /* Tant qu'on est pas … la fin du msg */
  393.     {
  394.         /*
  395.          * Identification du champ: 
  396.          */
  397.         *( ( unsigned long * ) tmp_msg_csr ) = field_ptr -> field_id;
  398.         tmp_msg_csr += sizeof( unsigned long );
  399.  
  400.         /*
  401.          * Longueur du champ: 
  402.          */
  403.         *( ( size_t * ) tmp_msg_csr ) = field_ptr -> length;
  404.         tmp_msg_csr += sizeof( unsigned long );
  405.  
  406.         /*
  407.          * Contenu du champ: 
  408.          */
  409.         memcpy( tmp_msg_csr, field_ptr -> info.string, field_ptr -> length);
  410.         last_string_adr = tmp_msg_csr;    /* On va conserver l'adresse du string du dernier champ */
  411.         tmp_msg_csr += field_ptr -> length;
  412.  
  413.         field_ptr = field_ptr -> next;    /* Pointe sur prochain segment */
  414.     }
  415.  
  416.     /*
  417.      * Checksum: 
  418.      */
  419.     for ( tmp_msg_check = tmp_msg_start; tmp_msg_check < tmp_msg_csr; tmp_msg_check++ )
  420.     {
  421.         checksum += *tmp_msg_check;
  422.     }
  423.  
  424.     /*
  425.      * InsŠre checksum dans le message: 
  426.      */
  427.     *(( unsigned int * ) last_string_adr) = checksum;
  428.  
  429.  
  430.     /*
  431.      * Pas (encore) de lock sur ce message:
  432.      */
  433.     clear_AllLocks( pCompactRec );
  434.  
  435.  
  436.     /*
  437.      * V‚rifie l'int‚grit‚ du compact record cr‚‚:
  438.      */
  439.     MCHECK( pCompactRec );
  440.     
  441.     return    pCompactRec;
  442. }
  443.  
  444.  
  445. /*
  446.  * -------------------------- DATA STORAGE ----------------------------
  447.  */
  448.  
  449.  
  450. /*
  451.  * Append_CompactRecToDB(-)
  452.  *
  453.  * Purpose:
  454.  * --------
  455.  * Ajoute un Record Compact … une base de donn‚es
  456.  *
  457.  * History:
  458.  * --------
  459.  * 05.12.94: moved out of Record_InFieldsToDB()
  460.  */
  461. void    Append_CompactRecToDB(
  462.             COMPACT_RECORD *    pCompactRec,    /* In: Ptr sur le Record … ajouter */
  463.             DATA_RECORDS    *    records )        /* In: Base de donn‚es concern‚e */
  464. {
  465.     COMPACT_RECORD    *old_last = records -> last_record;    /* Dernier message avant ajout du nouveau */
  466.  
  467.     /*    printf( "data records=%lu\n", records ); */
  468.     
  469.     /* 
  470.      * On va ajouter le message … la fin:
  471.      * Fixe pointeurs du nouveau message: 
  472.      */
  473.     pCompactRec -> prev = old_last;        /* Message pr‚c‚dent */
  474.     pCompactRec -> next = NULL;            /* Pas de message suivant */
  475.     
  476.     /* 
  477.      * Fixe pointeur du dernier message vers le nouveau: 
  478.      */
  479.     if ( old_last == NULL )
  480.     {    /*
  481.          * S'il n'existait pas encore de message: 
  482.          */
  483.         records -> first_record = pCompactRec;        /* On enregistre le premier message */
  484.     }
  485.     else
  486.     {    /*
  487.          * S'il existait d‚j… un message: 
  488.          */
  489.         old_last -> next = pCompactRec;
  490.     }
  491.     
  492.     /* 
  493.      * Fixe pointeur d'infos sur le nouveau dernier message: 
  494.      */
  495.     records -> last_record = pCompactRec;
  496.     
  497.     /*
  498.      * 1 message de plus: 
  499.      */
  500.     records -> nb_records ++;
  501.     
  502.     /* printf("\nNbre de messages=%ld\n", records -> nb_records ); */
  503. }
  504.  
  505.  
  506. /*
  507.  * -------------------------- DATA RETRIEVAL ----------------------------
  508.  */
  509.  
  510. /*
  511.  * Find_FieldinCompactRecord(-)
  512.  *
  513.  * Purpose:
  514.  * --------
  515.  * Cherche un Champ(Field) ds un Enregsitrement(Record)
  516.  *
  517.  * Notes:
  518.  * ------
  519.  * On renvoie le 1er trouv‚!
  520.  * (Il ne devrait normalement pas y en avoir plusieurs!)
  521.  *
  522.  * History:
  523.  * --------
  524.  * 07.12.94: fplanque: Created
  525.  * 24.01.95: sort si compact rec NULL
  526.  */
  527. COMPACT_FIELD * Find_FieldinCompactRecord(
  528.         const    COMPACT_RECORD *    cpCompactRec,
  529.         const ULONG                 cUL_FieldId )
  530. {
  531.     COMPACT_FIELD * cpCompactField;
  532.  
  533.     if( cpCompactRec == NULL )
  534.     {
  535.         return    NULL;
  536.     }
  537.  
  538.     for( cpCompactField = &(cpCompactRec -> data.CompactField); ; )
  539.     {
  540.         if( cpCompactField -> UL_FieldId == cUL_FieldId )
  541.         {    /*
  542.              * On a trouv‚ le champ qui nous int‚resse:
  543.              */
  544.             return    cpCompactField;
  545.         }
  546.     
  547.         if( cpCompactField -> UL_FieldId == 'FOOT' )
  548.         {    /*
  549.              * On est arriv‚ … la fin!
  550.              */
  551.             return    NULL;
  552.         }
  553.     
  554.         /*
  555.          * Passe au Field suivant:
  556.          */
  557.         cpCompactField = (COMPACT_FIELD *) ((UBYTE *)cpCompactField 
  558.                                     + sizeof(ULONG)         /* Longueur identifiant */
  559.                                     + sizeof(ULONG)        /* Longueur du champ 'longueur' */
  560.                                     + cpCompactField -> size_FieldLen);
  561.     }
  562.     
  563. }
  564.  
  565.  
  566. /*
  567.  * Find_CompactRecByField(-)
  568.  *
  569.  * Purpose:
  570.  * --------
  571.  * Cherche un Enregistrement(Record) ds une DB
  572.  * en fonction du contenu d'un des champs(Fields)
  573.  *
  574.  * Notes:
  575.  * ------
  576.  * On renvoie le 1er trouv‚
  577.  * (on considŠre qu'il s'agit d'une clef descriptive)
  578.  *
  579.  * History:
  580.  * --------
  581.  * 07.12.94: fplanque: Created
  582.  */
  583. COMPACT_RECORD * Find_CompactRecByField( 
  584.         const    COMPACT_RECORD *    cpCompactRec_Curr,    /* In: Ptr sur record o— doit commencer la recherche */
  585.         const ULONG                     cUL_FieldId,            /* In: Identifiant du champ qui sert de clef */
  586.         const char                 *    cpsz_FieldContent )    /* In: Clef de recheche */
  587. {
  588.     const COMPACT_FIELD * cpCpactFld;
  589.  
  590.     while( cpCompactRec_Curr != NULL )
  591.     {
  592.         /*
  593.          * Cherche le champ(Field) d‚sir‚ dans l'enregistrement(Record):
  594.          */
  595.         cpCpactFld = Find_FieldinCompactRecord( cpCompactRec_Curr, cUL_FieldId );
  596.         if( cpCpactFld != NULL )
  597.         {    /*
  598.              * On a trouv‚ le champ qui nous int‚resse:
  599.              * On v‚rifie le contenu
  600.              */
  601.             if( strcmp( cpCpactFld -> bytes, cpsz_FieldContent ) == 0 )
  602.             {    /*
  603.                  * Les champs correspondent!
  604.                  */
  605.                 return    (COMPACT_RECORD *) cpCompactRec_Curr;
  606.             }
  607.         }
  608.     
  609.         /*
  610.          * Passe au champ suivant:
  611.          */    
  612.         cpCompactRec_Curr = cpCompactRec_Curr -> next;
  613.     }
  614.     return    NULL;
  615. }
  616.  
  617.  
  618. /*
  619.  * -------------------------- DATA MANAGEMENT ----------------------------
  620.  */
  621.  
  622. /*
  623.  * clear_AllLocks(-)
  624.  *
  625.  * Purpose:
  626.  * --------
  627.  * Efface tous les locks sur un record
  628.  *
  629.  * Notes:
  630.  * ------
  631.  * A n'utiliser que lors de la cr‚ation d'un enregistrement!
  632.  * On risque des problŠmes s‚rieux dans le cas contraire!
  633.  *
  634.  * History:
  635.  * --------
  636.  * 17.05.94: fplanque: Created
  637.  */
  638. void    clear_AllLocks(                         
  639.             COMPACT_RECORD *pCompRec )     /* In:  Ptr sur record … initialiser */
  640. {
  641.  
  642.     pCompRec -> locks.nb_ReadLocks = 0;            /* Pas de lock de lecture */
  643.     pCompRec -> locks.b_XLock = FALSE0;            /* Pas de XLock */
  644.  
  645.  
  646.  
  647.  
  648. /*
  649.  * request_ReadLock(-)
  650.  *
  651.  * Purpose:
  652.  * --------
  653.  * Demande et positionne un Lock de lecture sur un enregistrement
  654.  * Lorsqu'une voie/fonction a demand‚ un ReadLock, elle peut librement
  655.  * lire le record, elle n'a, par contre, pas le droit de le modifier.
  656.  *
  657.  * Algorythm:
  658.  * ----------  
  659.  * PROVISOIRE, inachev‚
  660.  *
  661.  * Notes:
  662.  * ------
  663.  * Plusieurs voies/fonctions peuvent detenir simultan‚ment un ReadLock
  664.  * sur le mˆme record
  665.  *
  666.  * History:
  667.  * --------
  668.  * 17.05.94: fplanque: Created
  669.  */
  670. int    request_ReadLock(                 /* Out: !=0 si erreur */
  671.             COMPACT_RECORD *pCompRec ) /* In:  Ptr sur record … locker */
  672. {
  673.  
  674.     pCompRec -> locks.nb_ReadLocks ++;            /* Un lock de + */
  675.  
  676.     /* printf( "\nNbre de readlocks sur record courant: %d  \n", pCompRec -> locks.nb_ReadLocks ); */
  677.  
  678.     return    SUCCESS0;
  679.  
  680.  
  681.  
  682. /*
  683.  * release_ReadLock(-)
  684.  *
  685.  * Purpose:
  686.  * --------
  687.  * LibŠre le read lock qu'une vois/fonction avait sur un record
  688.  *
  689.  * Algorythm:
  690.  * ----------  
  691.  * PROVISOIRE, inachev‚
  692.  *
  693.  * Notes:
  694.  * ------
  695.  * Plusieurs voies/fonctions peuvent detenir simultan‚ment un ReadLock
  696.  * sur le mˆme record
  697.  *
  698.  * History:
  699.  * --------
  700.  * 17.05.94: fplanque: Created
  701.  */
  702. void    release_ReadLock(
  703.             COMPACT_RECORD *pCompRec )     /* In:  Ptr sur record … d‚locker */
  704. {
  705.     if( pCompRec -> locks.nb_ReadLocks <= 0 )
  706.     {
  707.         signale( "Lib‚ration d'un ReadLock inexistant!" );
  708.         pCompRec -> locks.nb_ReadLocks = 0;            /* S‚curit‚ */
  709.     }
  710.     else
  711.     {
  712.         pCompRec -> locks.nb_ReadLocks --;            /* Un lock de - */
  713.     }
  714.  
  715. }
  716.  
  717.  
  718.  
  719.  
  720.  
  721. /*
  722.  * change_ReadToXLock(-)
  723.  *
  724.  * Purpose:
  725.  * --------
  726.  * Essaie de modifier un ReadLock sur un record en XLock
  727.  *
  728.  * Algorythm:
  729.  * ----------  
  730.  * Si quelqu'un d'autre detient egalement un Readlock sur le record
  731.  * en question, le XLock ne peut pas ˆtre attribu‚.
  732.  *
  733.  * History:
  734.  * --------
  735.  * 17.05.94: fplanque: Created
  736.  */
  737. int    change_ReadToXLock(                     /* Out: !=0 si impossible */
  738.             COMPACT_RECORD *pCompRec )     /* In:  Ptr sur record … locker */
  739. {
  740.     /* printf( "\nNbre de readlocks sur record courant: %d  \n", pCompRec -> locks.nb_ReadLocks ); */
  741.  
  742.     /*
  743.      * Abandonne le ReadLock d‚j… d‚tenu et teste s'il y en a d'autres:
  744.      */
  745.     if( --(pCompRec -> locks.nb_ReadLocks) > 0 )            /* Un lock de - */
  746.     {    /*
  747.          * S'il y en a d'autres:
  748.          * On garde son ReadLock et la demande de XLOCK echoue
  749.          */
  750.         pCompRec -> locks.nb_ReadLocks ++;    
  751.         
  752.         return    FAILURE_1;
  753.     }
  754.     else
  755.     {    /*
  756.          * Place un XLock:
  757.          */
  758.         pCompRec -> locks.b_XLock = TRUE_1;
  759.         
  760.         return    SUCCESS0;
  761.     }
  762.  
  763.  
  764. /*
  765.  * release_XLock(-)
  766.  *
  767.  * Purpose:
  768.  * --------
  769.  * LibŠre le lock exclusif qu'on avait sur un record
  770.  *
  771.  * History:
  772.  * --------
  773.  * 17.05.94: fplanque: Created
  774.  */
  775. void    release_XLock(
  776.             COMPACT_RECORD *pCompRec )     /* In:  Ptr sur record … d‚locker */
  777. {
  778.     if( pCompRec -> locks.b_XLock == FALSE0 )
  779.     {
  780.         signale( "Lib‚ration d'un XLock inexistant!" );
  781.     }
  782.     else
  783.     {
  784.         pCompRec -> locks.b_XLock = FALSE0;            /* LibŠre lock */
  785.     }
  786.  
  787. }
  788.